From c140479ee2666bdaa3f355a88d2e27b06180e5e3 Mon Sep 17 00:00:00 2001 From: parkrrrr Date: Sun, 20 Jul 2003 19:46:57 +0000 Subject: [PATCH] add polygon filter --- gpsbabel/Makefile | 9 +- gpsbabel/README | 34 ++- gpsbabel/filter_vecs.c | 6 + gpsbabel/polygon.c | 300 ++++++++++++++++++++++++ gpsbabel/reference/polygon_allencty.txt | 177 ++++++++++++++ gpsbabel/reference/polygon_output.txt | 37 +++ gpsbabel/testo | 9 + 7 files changed, 567 insertions(+), 5 deletions(-) create mode 100644 gpsbabel/polygon.c create mode 100644 gpsbabel/reference/polygon_allencty.txt create mode 100644 gpsbabel/reference/polygon_output.txt diff --git a/gpsbabel/Makefile b/gpsbabel/Makefile index 89d1579a8..b20769b39 100644 --- a/gpsbabel/Makefile +++ b/gpsbabel/Makefile @@ -1,5 +1,5 @@ # add -DDEBUG_MEM to turn on memory allocation logging -CFLAGS=$(EXTRA_CFLAGS) -g -Icoldsync +CFLAGS=$(EXTRA_CFLAGS) -g -Icoldsync INSTALL_TARGETDIR=/usr/local/ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o \ @@ -7,7 +7,7 @@ FMTS=magproto.o gpx.o geo.o mapsend.o mapsource.o \ psp.o holux.o garmin.o tmpro.o tpg.o \ xcsv.o gcdb.o tiger.o internal_styles.o easygps.o quovadis.o gpilots.o -FILTERS=position.o duplicate.o arcdist.o +FILTERS=position.o duplicate.o arcdist.o polygon.o JEEPS=jeeps/gpsapp.o jeeps/gpscom.o \ jeeps/gpsmath.o jeeps/gpsmem.o \ @@ -19,8 +19,9 @@ JEEPS=jeeps/gpsapp.o jeeps/gpscom.o \ COLDSYNC=coldsync/util.o coldsync/pdb.o -OBJS=main.o queue.o route.o waypt.o filter_vecs.o util.o vecs.o mkshort.o csv_util.o \ +LIBOBJS = queue.o route.o waypt.o filter_vecs.o util.o vecs.o mkshort.o csv_util.o \ $(COLDSYNC) $(GARMIN) $(JEEPS) $(FMTS) $(FILTERS) +OBJS = main.o $(LIBOBJS) .c.o: $(CC) -c $(CFLAGS) $< -o $@ @@ -70,6 +71,7 @@ release: # Machine generated from here down. +arcdist.o: arcdist.c defs.h queue.h cetus.o: cetus.c defs.h queue.h coldsync/palm.h coldsync/pdb.h quovadis.o: quovadis.c defs.h queue.h coldsync/palm.h coldsync/pdb.h quovadis.h copilot.o: copilot.c defs.h queue.h coldsync/palm.h coldsync/pdb.h @@ -90,6 +92,7 @@ gpsutil.o: gpsutil.c defs.h queue.h magellan.h gpx.o: gpx.c defs.h queue.h holux.o: holux.c defs.h queue.h holux.h internal_styles.o: internal_styles.c defs.h queue.h +polygon.o: polygon.c defs.h queue.h magnav.o: magnav.c defs.h queue.h coldsync/palm.h coldsync/pdb.h magproto.o: magproto.c defs.h queue.h magellan.h main.o: main.c defs.h queue.h diff --git a/gpsbabel/README b/gpsbabel/README index fafaaebf0..3b5963aab 100644 --- a/gpsbabel/README +++ b/gpsbabel/README @@ -445,7 +445,7 @@ DATA FILTERS locations. The result would be a GPX file that more than likely contains only unique points and point data. - DISTANCE ALONG A ROUTE + DISTANCE ALONG A ROUTE (ARC) The arc filter is designed to include points based on their proximity to an arc, which is a series of connected line @@ -472,7 +472,9 @@ DATA FILTERS that distance is declared on the command line with the distance=X.XX option to the filter. Distance options may be expressed in miles (distance=3M) or kilometers (distance=3K). - The default is zero miles. + The default is zero miles. You may also specify the exclude option, + which causes GPSBabel to only include points that are further than + the specified distance from the arc. For example, assuming the arc above is in a file called "lima_rd.txt": @@ -482,6 +484,34 @@ DATA FILTERS would include only points within one mile of the section of Lima Road covered by the arc. + POLYGON + + The polygon filter includes points if they are inside of a polygon. + A polygon file looks like an arc file, except that the arc it + describes must be a closed cycle. That is, for a simple polygon, + the first and last points must be the same. Here's a square: + + # A square (not really) polygon + 41.0000 -85.0000 + 41.0000 -86.0000 + 42.0000 -86.0000 + 42.0000 -85.0000 + 41.0000 -85.0000 + + Polygons may include islands and holes. To specify an island or a + hole, just append it to the main polygon. + + As with the arc filter, you specify a polygon by specifying the name + of the polygon that contains it, using the file option. You can also + specify the exclude option, which reverses the operation of the filter + so that it only includes points that are NOT in the polygon. + + For example, assume you have a polygon file that defines the border of + your county, called mycounty.txt. This command line will give you only + the points in your county: + + gpsbabel -i geo -f 1.loc -x polygon,file=mycounty.txt \ + -o mapsend -F 2.wpt COMMON USAGE diff --git a/gpsbabel/filter_vecs.c b/gpsbabel/filter_vecs.c index e394df284..791a77cf3 100644 --- a/gpsbabel/filter_vecs.c +++ b/gpsbabel/filter_vecs.c @@ -32,6 +32,7 @@ extern filter_vecs_t position_vecs; extern filter_vecs_t radius_vecs; extern filter_vecs_t duplicate_vecs; extern filter_vecs_t arcdist_vecs; +extern filter_vecs_t polygon_vecs; static fl_vecs_t filter_vec_list[] = { @@ -55,6 +56,11 @@ fl_vecs_t filter_vec_list[] = { "arc", "Include Only Points Within Distance of Arc", }, + { + &polygon_vecs, + "polygon", + "Include Only Points Inside Polygon", + }, { NULL, NULL, diff --git a/gpsbabel/polygon.c b/gpsbabel/polygon.c new file mode 100644 index 000000000..fbc7ae56c --- /dev/null +++ b/gpsbabel/polygon.c @@ -0,0 +1,300 @@ +/* + Inside/Outside polygon filter + + Copyright (C) 2002 Robert Lipe, robertlipe@usa.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA + + */ +#include +#include +#include "defs.h" + +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +#define MYNAME "Polygon filter" + +extern queue waypt_head; + +static double pos_dist; +static char *polyfileopt = NULL; +static char *exclopt = NULL; + +#define OUTSIDE 0 +#define INSIDE 1 +#define LIMBO 2 +#define LIMBO_UP 4 +#define LIMBO_BEGIN 8 +#define BEGIN_UP 16 +#define BEGIN_HOR 32 +#define UP 64 + +typedef struct { + unsigned short state; +} extra_data; + +static +arglist_t polygon_args[] = { + {"file", &polyfileopt, "File containing vertices of polygon"}, + {"exclude", &exclopt, "Exclude points inside the polygon"}, + {0, 0, 0} +}; + +static void polytest ( double lat1, double lon1, + double lat2, double lon2, + double lat3, double lon3, + unsigned short *state, int first, int last ) { + + if ( lat1 == lat3 ) { + if ( lat2 < lat3 ) { + /* going down */ + if (*state & LIMBO) { + if ( *state & LIMBO_UP ) { + *state = *state ^ INSIDE; + } + *state = *state & ~LIMBO &~LIMBO_UP; + } + else if (*state & LIMBO_BEGIN) { + if ( *state & BEGIN_HOR ) { + *state = *state & ~BEGIN_HOR; + } + else if ( last ) { + if ( *state & BEGIN_UP ) { + *state = *state ^ INSIDE; + } + *state = *state & ~LIMBO_BEGIN & ~BEGIN_UP; + } + } + else if ( first && (lon1 > lon3)) { + *state |= LIMBO_BEGIN; + } + } + else if ( lat2 == lat3 ) { + if ( first & (lon1 > lon3 || lon2 > lon3)) { + *state |= LIMBO_BEGIN | BEGIN_HOR; + } + else if (last && (*state & LIMBO_BEGIN) && (*state & LIMBO)) { + if ( (!!(*state & LIMBO_UP)) != (!!(*state & BEGIN_UP))) { + *state = *state ^ INSIDE; + } + *state = *state & ~LIMBO & ~LIMBO_UP & + ~LIMBO_BEGIN & ~BEGIN_UP; + } + else if ( *state & LIMBO ) { + /* do nothing */ + } + else { + if ( lon1 <= lon3 && lon2 > lon3 ) { + if ( *state & UP ) { + *state = *state | LIMBO_UP & ~UP; + } + *state = *state | LIMBO; + } + } + } + else { + /* going up */ + if (*state & LIMBO) { + if ( !(*state & LIMBO_UP) ) { + *state = *state ^ INSIDE; + } + *state = *state & ~LIMBO & ~LIMBO_UP; + } + else if (*state & LIMBO_BEGIN) { + if ( *state & BEGIN_HOR ) { + *state = *state & ~BEGIN_HOR | BEGIN_UP; + } + else if ( last ) { + if ( !(*state & BEGIN_UP) ) { + *state = *state ^ INSIDE; + } + *state = *state & ~LIMBO_BEGIN & ~BEGIN_UP; + } + } + else if ( first && (lon1 > lon3)) { + *state |= LIMBO_BEGIN | BEGIN_UP; + } + } + *state = *state & ~UP; + } + else if ( lat2 == lat3 ) { + if ( lat1 < lat3 ) { + if ( last ) { + if ( *state & BEGIN_UP ) { + *state = *state ^ INSIDE; + } + *state = *state & ~LIMBO_BEGIN & ~BEGIN_UP; + } + else if ( lon2 > lon3 ) { + *state |= LIMBO; + } + } + /* no case for lat1==lat3; that's above */ + else { + if ( last ) { + if ( !(*state & BEGIN_UP) ) { + *state = *state ^ INSIDE; + } + *state = *state & ~LIMBO_BEGIN & ~BEGIN_UP; + } + else if ( lon2 > lon3 ) { + *state |= LIMBO | LIMBO_UP; + } + else { + *state |= UP; + } + } + } + else { + if ( (lat1 > lat3 && lat2 < lat3) || + (lat1 < lat3 && lat2 > lat3)) { + /* we only care if the lines might intersect */ + if ( lon1 > lon3 && lon2 > lon3 ) { + *state = *state ^ INSIDE; + } + else if (!(lon1 <= lon3 && lon2 <= lon3)) { + /* we're inside the bbox of a diagonal line. math time. */ + double loni = (lon2-lon1)/(lat2-lat1)*(lat3-lat1); + if ( loni > lon3 ) { + *state = *state ^ INSIDE; + } + } + } + } + +} + +#define BADVAL 999999 + +void +polygon_process(void) +{ + queue * elem, * tmp; + waypoint * waypointp; + waypoint ** comp; + int i, wc; + queue temp_head; + extra_data *ed; + double lat1, lon1, lat2, lon2; + double olat, olon; + int fileline = 0; + int first = 1; + int last = 0; + + FILE *polyfile = fopen( polyfileopt, "r" ); + if ( polyfile == NULL ) { + fatal(MYNAME ":Can't open %s for reading.\n",polyfileopt); + } + + olat = olon = lat1 = lon1 = lat2 = lon2 = BADVAL; + while ( !feof(polyfile)) { + char line[200]; + char *pound = NULL; + int argsfound = 0; + + fgets( line, sizeof(line), polyfile ); + + fileline++; + + pound = strchr( line, '#' ); + if ( pound ) *pound = '\0'; + + lat2 = lon2 = BADVAL; + argsfound = sscanf( line, "%lf %lf", &lat2, &lon2 ); + + if ( argsfound != 2 && strspn(line, " \t\n") < strlen(line)) { + fprintf( stderr, "%s: Warning: Polygon file contains unusable vertex on line %d.\n", MYNAME, fileline ); + } + else if ( lat1 != BADVAL && lon1 != BADVAL && + lat2 != BADVAL && lon2 != BADVAL ) { + QUEUE_FOR_EACH(&waypt_head, elem, tmp) { + + waypointp = (waypoint *)elem; + if ( waypointp->extra_data ) { + ed = waypointp->extra_data; + } + else { + ed = xcalloc(1, sizeof(*ed)); + ed->state = OUTSIDE; + waypointp->extra_data = ed; + } + if ( olat != BADVAL && olon != BADVAL && + olat == lat2 && olon == lon2 ) { + last = 1; + } + polytest( lat1, lon1, lat2, lon2, + waypointp->position.latitude.degrees, + waypointp->position.longitude.degrees, + &ed->state, first, last ); + first = 0; + last = 0; + } + } + if ( olat != BADVAL && olon != BADVAL && + olat == lat2 && olon == lon2 ) { + olat = BADVAL; + olon = BADVAL; + lat1 = BADVAL; + lon1 = BADVAL; + first = 1; + } + else if ( lat1 == BADVAL || lon1 == BADVAL ) { + olat = lat2; + olon = lon2; + lat1 = lat2; + lon1 = lon2; + } + else { + lat1 = lat2; + lon1 = lon2; + } + } + + fclose(polyfile); + + + QUEUE_FOR_EACH(&waypt_head, elem, tmp) { + waypoint *wp = (waypoint *) elem; + ed = wp->extra_data; + wp->extra_data = NULL; + if ( ed ) { + if (((ed->state & INSIDE) == OUTSIDE ) == (exclopt == NULL)) { + waypt_del(wp); + waypt_free(wp); + continue; + } + xfree( ed ); + } + } +} + +void +polygon_init(const char *args) { + /* do nothing */ +} + +void +polygon_deinit(void) { + /* do nothing */ +} + +filter_vecs_t polygon_vecs = { + polygon_init, + polygon_process, + polygon_deinit, + polygon_args +}; diff --git a/gpsbabel/reference/polygon_allencty.txt b/gpsbabel/reference/polygon_allencty.txt new file mode 100644 index 000000000..b63e58e87 --- /dev/null +++ b/gpsbabel/reference/polygon_allencty.txt @@ -0,0 +1,177 @@ +41.270000 -84.847384 +41.271057 -84.806490 +41.271079 -84.803581 +41.271079 -84.803581 +41.270942 -84.803580 +41.252531 -84.803492 +41.252531 -84.803492 +41.184959 -84.803475 +41.173889 -84.803472 +41.173203 -84.803594 +41.164649 -84.803413 +41.164169 -84.803420 +41.161573 -84.803460 +41.154117 -84.803573 +41.140520 -84.803780 +41.130773 -84.803501 +41.121414 -84.803234 +41.096783 -84.803341 +41.096783 -84.803341 +41.089302 -84.803374 +41.077432 -84.803367 +41.009551 -84.803325 +40.989209 -84.803313 +40.989209 -84.803313 +40.922377 -84.802935 +40.922377 -84.802935 +40.920577 -84.880807 +40.920577 -84.880807 +40.920311 -84.899804 +40.920311 -84.899804 +40.920237 -84.906200 +40.920237 -84.906200 +40.919632 -84.939126 +40.919632 -84.939638 +40.918588 -84.997291 +40.918588 -84.997291 +40.918447 -85.015168 +40.918447 -85.016068 +40.918447 -85.017668 +40.918047 -85.049068 +40.918047 -85.053468 +40.917847 -85.064268 +40.917847 -85.073868 +40.917847 -85.073868 +40.917447 -85.109669 +40.917447 -85.109669 +40.917247 -85.133662 +40.917247 -85.138269 +40.916547 -85.167070 +40.916947 -85.223371 +40.917047 -85.261571 +40.917047 -85.261571 +40.917047 -85.267360 +40.917047 -85.267360 +40.917032 -85.270180 +40.917023 -85.271123 +40.917011 -85.272372 +40.917011 -85.272372 +40.916994 -85.274150 +40.916994 -85.274150 +40.916947 -85.284172 +40.916947 -85.285948 +40.916947 -85.287972 +40.916947 -85.289672 +40.916947 -85.290204 +40.916947 -85.290204 +40.917046 -85.324973 +40.916946 -85.325373 +40.917046 -85.335973 +40.917046 -85.335973 +40.931446 -85.335873 +40.934746 -85.335973 +40.945846 -85.335573 +40.946246 -85.335673 +40.960346 -85.335673 +40.966746 -85.335573 +40.966746 -85.335573 +40.973192 -85.335418 +40.973192 -85.335418 +41.002047 -85.335374 +41.005347 -85.335274 +41.005347 -85.335274 +41.019947 -85.335574 +41.019947 -85.335574 +41.023138 -85.335574 +41.023138 -85.335574 +41.028400 -85.335626 +41.028400 -85.335626 +41.028680 -85.335631 +41.028680 -85.335631 +41.034047 -85.335774 +41.036347 -85.336074 +41.036347 -85.336074 +41.043516 -85.336249 +41.043516 -85.336249 +41.044447 -85.336274 +41.059047 -85.336574 +41.074947 -85.336974 +41.074947 -85.336974 +41.078620 -85.336974 +41.078620 -85.336974 +41.081370 -85.337035 +41.081370 -85.337035 +41.082627 -85.337075 +41.084247 -85.337075 +41.084247 -85.337075 +41.089647 -85.337275 +41.133759 -85.337800 +41.143299 -85.337827 +41.143299 -85.337827 +41.145540 -85.337834 +41.145540 -85.337834 +41.151009 -85.338178 +41.172790 -85.338402 +41.179120 -85.338552 +41.179260 -85.309842 +41.205086 -85.309537 +41.208912 -85.309716 +41.208912 -85.309716 +41.209609 -85.309724 +41.209609 -85.309724 +41.218262 -85.309657 +41.218720 -85.309808 +41.228211 -85.309910 +41.229675 -85.309950 +41.229675 -85.309950 +41.233139 -85.309660 +41.233139 -85.309660 +41.235062 -85.309506 +41.235192 -85.309502 +41.246997 -85.309775 +41.250047 -85.309586 +41.251009 -85.309143 +41.264071 -85.307748 +41.264071 -85.307748 +41.263809 -85.262791 +41.263851 -85.255698 +41.263851 -85.255698 +41.263850 -85.255648 +41.263850 -85.255648 +41.263805 -85.249531 +41.264283 -85.192097 +41.264283 -85.192097 +41.264449 -85.182307 +41.264449 -85.182307 +41.264820 -85.154950 +41.264820 -85.154950 +41.264961 -85.144213 +41.264961 -85.144213 +41.265046 -85.137394 +41.265046 -85.137394 +41.265091 -85.135030 +41.265829 -85.086692 +41.265562 -85.077749 +41.265562 -85.077749 +41.265756 -85.065254 +41.265756 -85.065254 +41.265822 -85.061017 +41.265822 -85.061017 +41.265860 -85.058621 +41.266469 -85.020092 +41.266557 -85.016245 +41.266557 -85.016245 +41.266740 -85.008277 +41.266740 -85.008277 +41.267781 -84.962627 +41.268149 -84.941620 +41.268218 -84.938770 +41.268218 -84.938164 +41.268368 -84.926845 +41.268627 -84.914822 +41.268963 -84.901055 +41.268963 -84.901055 +41.268974 -84.900612 +41.268974 -84.900612 +41.269170 -84.892632 +41.270000 -84.847384 diff --git a/gpsbabel/reference/polygon_output.txt b/gpsbabel/reference/polygon_output.txt new file mode 100644 index 000000000..3f589a727 --- /dev/null +++ b/gpsbabel/reference/polygon_output.txt @@ -0,0 +1,37 @@ +BEGIN SYMBOL +41.14703, -85.11092, N.E.R.D. by Enos Shenk Unknown Cache (3/3) +41.13940, -85.10142, Fallen Timbers by TeamMJ Traditional Cache (2/2) +41.14415, -85.14415, Historic Iron Bridges by Genoist (1/2 of TeamSJ1) Locationless (Reverse) Cache (1/1) +41.12890, -85.11163, Mastadon Trek 2 by Genoist and Dogvetusa Traditional Cache (2/2) +41.16413, -85.14688, NYC Trail by VistaAL Traditional Cache (1/1.5) +41.15900, -85.15418, Craftily Concealed Containers by Warm Fuzzies Multi-Cache (4/2) +41.12210, -85.11097, Land of Lost Auto Parts by Genoist and The Zymurgist Traditional Cache (1/5) +41.17732, -85.15117, The Farm by AParks1569 Traditional Cache (1.5/1.5) +41.10757, -85.13087, Swonderful by Genoist and The Zymurgist Traditional Cache (2/5) +41.12733, -85.06728, Dr. Mengerson I Preserve by Genoist Traditional Cache (2/2) +41.10417, -85.15167, Clue by Warm Fuzzies Multi-Cache (3.5/2) +41.10823, -85.16212, Son of Pez by Enos Shenk Traditional Cache (1.5/1.5) +41.09278, -85.14073, Urbana #3: Dodgy Deals by Enos Shenk Traditional Cache (2.5/1.5) +41.09258, -85.09258, Secret Squirrels by Enos Shenk & Panic! Unknown Cache (4/1) +41.08748, -85.13762, A King's Ransom by Team ABC and The GeoStars Team Traditional Cache (1.5/1) +41.08427, -85.13597, Urbana #4: The City She Loves Me by Enos Shenk & Athena Traditional Cache (3.5/2) +41.08582, -85.07230, Caribbean Cache by Genoist and Dogvetusa Traditional Cache (3/2) +41.08190, -85.17180, Earthling Vector Luna- 2nd Phase by Earthling and Heavenbound Traditional Cache (1/1.5) +41.08400, -85.05387, Earthling Vector Sol by Earthling & Heavenbound Traditional Cache (1.5/1.5) +41.20673, -85.03985, The Sarsaparilla Cache by Cashconnect Traditional Cache (2/1.5) +41.06353, -85.13400, Sky High by Enos Shenk Virtual Cache (1/3) +41.09880, -85.21725, We Support Our Troops by Genoist and The Zymurgist Traditional Cache (2/2.5) +41.06950, -85.19750, Shortwave by Warm Fuzzies Unknown Cache (4/2.5) +41.06255, -85.04757, Starfall by Enos Shenk Traditional Cache (2/2.5) +41.07482, -85.01957, Fly Like an Eagle by Team SJ1 Traditional Cache (2/2) +41.04714, -85.16617, Perfectly Perplexing Puzzles by Warm Fuzzies Multi-Cache (5/3.5) +41.07197, -85.01863, Arrow Haven (2/4) by Genoist Traditional Cache (2/2.5) +41.07183, -85.01850, Heat Death (3/4) by Genoist Traditional Cache (2/3) +41.06827, -85.01655, Abbadon by Genoist Traditional Cache (1.5/4) +41.01503, -85.13290, Earthling Vector Pluto by Earthling & Heavenbound Traditional Cache (1/1.5) +41.26535, -84.98950, Outstanding In Its Field Cache by kwbach Traditional Cache (2/2) +41.00470, -85.05742, Earthling Vector Perelandra by Earthling & Heavenbound Multi-Cache (4/1.5) +41.04247, -85.27570, KWAANTINAKAANI by Northmill Jo-Jo Beans and E-Bone Letterbox Hybrid (2/1) +41.01760, -85.25190, Earthling Vector Terra by Earthling & Heavenbound Traditional Cache (1.5/2.5) +40.97610, -85.22277, 47520 Feet by kidCraZy Traditional Cache (1/1.5) +END diff --git a/gpsbabel/testo b/gpsbabel/testo index 8ea01968e..9a8291cba 100755 --- a/gpsbabel/testo +++ b/gpsbabel/testo @@ -337,3 +337,12 @@ ${PNAME} -i xmap -f reference/arcdist_input.txt \ -o xmap -F ${TMPDIR}/arcdist.txt compare ${TMPDIR}/arcdist.txt reference/arcdist_output.txt +# +# Polygon filter +# +rm -f ${TMPDIR}/polygon.txt +${PNAME} -i xmap -f reference/arcdist_input.txt \ + -x polygon,file=reference/polygon_allencty.txt \ + -o xmap -F ${TMPDIR}/polygon.txt +compare ${TMPDIR}/polygon.txt reference/polygon_output.txt + -- 2.30.2